/*
 * Copyright @ 苏州瑞云信息技术有限公司 All rights reserved.
 */
package work.base.data.stream;

import work.entity.Student;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 *
 * reduce() partitioningBy()的用法
 *
 * parallelStream()并行流处理可以减少时间
 * 相对于串行流可以减少一半时间 但需要注意线程安全问题
 *
 * @author Sakura Shen
 * @date 2021/9/27
 */
public class StreamTest02 {
    public static void main(String[] args){

        Stream<Integer> stream = Stream.of(1,2,6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14);
        // 1 筛选与切片
        Stream<Integer> newStream = stream.filter(s -> s > 5) //6 6 7 9 8 10 12 14 14
                .distinct() //6 7 9 8 10 12 14
                .skip(2) //9 8 10 12 14
                .limit(2); //9 8
        newStream.forEach(System.out::println);


        //经过测试，当元素个数小于24时，并行时线程数等于元素个数，当大于等于24时，并行时线程数为16
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24);
        // 2 reduce最后的结果是一个数据 reduce方法用于对stream中元素进行聚合求值，
        // 最常见的用法就是将stream中一连串的值合成为单个值
        Integer v = list.stream().reduce((x1, x2) -> x1 + x2).get();
        System.out.println(v);   // 300
        Integer v1 = list.stream().reduce(10, (x1, x2) -> x1 + x2);
        System.out.println(v1);   // 300


        // 3 list转成map 两种常见的情况
        Student s1 = new Student("aa", 10);
        Student s2 = new Student("bb", 20);
        Student s3 = new Student("cc", 10);
        List<Student> userList = Arrays.asList(s1, s2, s3);
        // value是实体对象
        Map<String, Student> studentMap = userList.stream().collect(Collectors.toMap(Student::getName, Student->Student));
        // value是实体对象的某个字段
        Map<String, Integer> map1 = userList.stream().collect(Collectors.toMap(Student::getName, Student::getIndex));
        System.out.println("studentMap");
        System.out.println(studentMap);

        // 4 求最值 max min
        // max和min方法的参数都是Comparator接口
        // 4.1 集合中的实体对象的某个字段的最值 先map映射 再max求最值
        Integer maxAge = userList.stream().map(Student::getIndex).max(Integer::compare).get();
        Integer maxAge1 = userList.stream().map(Student::getIndex).max((k1,k2)->k1-k2).get();
        Integer maxAge2 = userList.stream().map(Student::getIndex).max(Comparator.comparingInt(k -> k)).get();
        // 4.2 集合中最值的某个实体对象
        // Comparator.comparing() 是把对象某个方法的返回值 进行compareTo()调用比较
        // 比较的字段有null 程序会报错 要先把为null的数据过滤掉
        Student maxAgeStudent = userList.stream().filter(k -> null != k.getIndex()).max(Comparator.comparing(Student::getIndex)).orElse(null);
        //4.3 Integer String类型的求最值
        // 使用自身的compare或者compareTo()方法  作为Comparator接口的 compare(T o1, T o2) 方法的实现
        List<String> list_str = Arrays.asList("yy", "ff", "dd");
        String maxS = list_str.stream().max(String::compareTo).get();
        String minS = list_str.stream().min(String::compareTo).get();



        // 5 分组 能把数据分成多个部分
        Map<Integer, List<Student>> ageMap = userList.stream().collect(Collectors.groupingBy(Student::getIndex));
        // HashMap的values() 得到value的集合 Collection
        // parallelStream  并行流处理 类似于多线程
        ageMap.values().parallelStream().forEach(list_a -> {
            // 部门信息
            String name = list_a.get(0).getName();
            System.out.println(name);
        });
        // 分区 只能将数据分为两组也就是ture和false两组数据。
        Map<Boolean, List<Student>> partMap = userList.stream().collect(Collectors.partitioningBy(vv -> vv.getIndex() > 10));

        System.out.println("AAAA");

    }
}
